import 'dart:async';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/cupertino.dart';
import 'package:full_display/common/url_path.dart';
import 'package:full_display/provide/cmd_provider.dart';
import 'package:full_display/provide/drawer_provider.dart';
import 'package:full_display/unit/log/log_util.dart';
import 'package:provider/provider.dart';
import 'package:web_socket_channel/io.dart';
import 'dart:convert' as convert;

class WebSocketUtils {
  WebSocketUtils._internal();
  static final WebSocketUtils _webSocketutils = WebSocketUtils._internal();
  late IOWebSocketChannel? _channel;
  late Timer? _timer;
  late String deviceID;
  late int order = 1;
  late CMDProvider _cmdData;
  late DrawerProvider _drawerData;
  factory WebSocketUtils() {
    return _webSocketutils;
  }
  void initSocket() {
    _channel = IOWebSocketChannel.connect(Uri.parse(UrlPath.WS_URL));
    _channel!.sink.add('');
    _channel!.stream.listen(this.onData, onError: onError, onDone: onDone);
    startCountdownTimer();
  }

  void initData(BuildContext context) {
    _cmdData = context.watch<CMDProvider>();
    _drawerData = context.watch<DrawerProvider>();
    Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
      logD("result$result");
      if (result == ConnectivityResult.wifi) {
        _channel!.sink.close();
        _timer!.cancel();
        initSocket();
      }
    });
  }

  ///开启心跳
  void startCountdownTimer() {
    const oneSec = Duration(seconds: 3);
    callback(timer) {
      if (_channel == null) {
        initSocket();
      }
    }

    _timer = Timer.periodic(oneSec, callback);
  }

  void sendCustomMessage(int type, {dynamic content}) {
    switch (type) {
      case 47:
        Map<String, dynamic> params = Map<String, dynamic>();
        params = {
          "cmd": 0x2F,
          "source": 0,
          "destination": 0,
          "order": 2,
          "pack_order": 1,
          "pack_count": 1,
          "version_code": 1,
          "properties": {
            "type": 1,
            "id": deviceID,
            "mode": 1,
            "ishot": content["ishot"],
            "ssid": content["ssid"],
            "password": content["password"]
          }
        };
        print("params ------> ${convert.jsonEncode(params)}");
        if (_channel != null) {
          _channel!.sink.add(convert.jsonEncode(params));
        }
        break;
      case 48:
        Map<String, dynamic> params = Map<String, dynamic>();
        params = {
          "cmd": 0x30,
          "source": 0,
          "destination": 0,
          "order": 2,
          "pack_order": 1,
          "pack_count": 1,
          "version_code": 1,
          "properties": {
            "type": 0,
            "id": deviceID,
            "value": 1,
            "bluetooth": content['bluetooth'] ?? '',
            "password": content['password'] ?? ''
          }
        };
        print("params ------> ${convert.jsonEncode(params)}");
        if (_channel != null) {
          _channel!.sink.add(convert.jsonEncode(params));
        }
        break;
      case 52:
        Map<String, dynamic> params = Map<String, dynamic>();
        //1-立即更新
        //5-显示设备信息
        //8-打开状态窗体
        //9-关闭状态窗体
        //17-设备设备状态上报时间间隔以秒为单位
        //18-设备文件列表上报时间间隔
        //19-显示设备SN码
        //20-不显示设备SN码
        //21-开启测灯模式
        //22-关闭测灯模式
        //23-设置时间
        //24-设置色调
        if (order > 255) {
          order = 1;
        }
        order++;
        params = {
          "cmd": 0x34,
          "source": "0",
          "destination": 0,
          "order": order,
          "version_code": 1,
          "pack_order": 1,
          "pack_count": 1,
          "properties": {
            "type": 1,
            "id": deviceID,
            "control_type": content['value'],
            "second": 0,
            "date_time": '',
            "r_tone": 0,
            'g_tone': 0,
            'b_tone': 0,
          },
        };
        if (content['value'] == 17 || content['value'] == 18) {
          params["properties"]['second'] = 20;
        } else if (content['value'] == 23) {
          params["properties"]['date_time'] = content['time'];
        } else if (content['value'] == 24) {
          params["properties"]['r_tone'] = content['r'];
          params["properties"]['g_tone'] = content['g'];
          params["properties"]['b_tone'] = content['b'];
        }
        print("params ------> ${convert.jsonEncode(params)}");
        if (_channel != null) {
          _channel!.sink.add(convert.jsonEncode(params));
        }
        break;
      case 53:
        Map<String, dynamic> params = Map<String, dynamic>();

        params = {
          "cmd": 0x35,
          "source": 0,
          "destination": 0,
          "pack_order": 1,
          "pack_count": 1,
          "version_code": 1,
          "properties": {"type": 0, "id": 0, "time": content}
        };

        print("params ------> ${convert.jsonEncode(params)}");
        if (_channel != null) {
          _channel!.sink.add(convert.jsonEncode(params));
        }
        break;
      case 65:
        Map<String, dynamic> params = Map<String, dynamic>();

        params = {
          "cmd": 0x41,
          "source": 0,
          "destination": 0,
          "order": 2,
          "pack_order": 1,
          "pack_count": 1,
          "version_code": 1,
          "properties": {
            "type": 0,
            "id": deviceID,
            "file_type": 2,
            "file_id": 0,
            "play_count": 1,
            "play_order": 1,
            "residencetime": 1,
            "display_mode": 0,
            "file_name": DateTime.now().millisecondsSinceEpoch,
            "pack_number": 0
          }
        };
        print("params ------> ${convert.jsonEncode(params)}");
        if (_channel != null) {
          _channel!.sink.add(convert.jsonEncode(params));
        }
        break;
      case 66:
        if (order > 255) {
          order = 1;
        }
        order++;
        Map<String, dynamic> params = Map<String, dynamic>();

        if (content["type"] == '1') {
          params = {
            "cmd": 0x42,
            "source": 0,
            "destination": 0,
            "order": order,
            "pack_order": 1,
            "version_code": 1,
            "properties": {
              "type": 0,
              "id": deviceID,
              "file_id": 0,
              "file_type": 1,
              "text": "",
              "color": "#ffaa00",
              "animation": "0",
              "play_count": 1,
              "residencetime": 15,
              "display_mode": 0,
              "file_name": DateTime.now().millisecondsSinceEpoch,
              "pack_number": 0
            }
          };
          print("params1 ------> ${convert.jsonEncode(params)}");
          if (_channel != null) {
            _channel!.sink.add(convert.jsonEncode(params));
          }
        } else if (content["type"] == '3') {
          params = {
            'cmd': 0x42,
            'source': 0, //发送者id
            'destination': 0, //接受者id
            'order': order, //发送序号
            'pack_order': 1, //分包序号
            'pack_count': 1, //分包数
            'version_code': 1, //版本号
            'properties': {
              "type": 0, //0-Device 1-Splicing 2-House
              "id": deviceID, //Device id
              "file_id": 1,
              "file_type": 3, //1-图片 2-视频 3-文字
              "play_count": 1, //file play count
              "residencetime":
                  content["residencetime"], //停留时间及播放时长，-1代表一直循环，0代表不播放
              "text": content["text"], //文字 您好
              "color": content["color"], //色值 #CC00FF #EE0022
              "animation": 1, //动画索引  1,2,3,4,5
              "file_name": "", //文件名
              "pack_number": 0, // 图片或视频数据包号
            }
          };
          print("params3 ------> ${convert.jsonEncode(params)}");
          if (_channel != null) {
            _channel!.sink.add(convert.jsonEncode(params));
          }
        } else {
          if (_channel != null) {
            // print("params2 ------> ${content["data"]}");
            _channel!.sink.add(content["data"]);
          }
        }

        break;
      case 67:
        Map<String, dynamic> params = Map<String, dynamic>();
        params = {
          "cmd": 0x43,
          "source": 0,
          "destination": 0,
          "order": 2,
          "pack_order": 1,
          "pack_count": 1,
          "version_code": 1,
          "properties": {
            "type": 0,
            "id": deviceID,
            "file_id": content.toString(),
          }
        };
        print("params ------> ${convert.jsonEncode(params)}");
        if (_channel != null) {
          _channel!.sink.add(convert.jsonEncode(params));
        }
        break;
      default:
    }
  }

  void sendMessage(int value, {dynamic content}) {
    Map<String, dynamic> params = Map<String, dynamic>();
    //type
    //0-关机,
    //1-开机,
    //2-重启,
    //6-播放指定文件,
    //7-亮度调节,
    //0xB-音量调节,
    //0x10-角度调节,
    //0x11-打开角度,
    //0x12-关闭角度,
    //0x20-拼接位置测试,
    //0x21-播放模式,
    //0x22-设置转速,
    //0x23-正转,
    //0x24-反转,
    //0x25-通电转,
    //0x26-通电不转,
    //0x27-启停记忆

    //"file_id":0//当“value = 6”时有效，表示指定播放的文件ID
    //"brightness_value":0//当“value = 7”时, 指定设备的亮度,亮度值为0 to 15.
    //"adjustment_value":0//当 “value = 0x10”时有效, 当"adjustment_value",为0时表示角度减，1时表示角度加
    if (order > 255) {
      order = 1;
    }
    order++;
    params = {
      "cmd": 0x2e,
      "source": "0",
      "destination": 0,
      "order": order,
      "version_code": 1,
      "pack_order": 1,
      "pack_count": 1,
      "properties": {
        "type": 1,
        "id": deviceID,
        "value": value,
        "file_id": 0,
        "brightness_value": 0,
        "adjustment_value": 0,
        'volume_value': 0,
        'play_mode': 0,
        'speed_value': 0,
      },
    };
    if (value == 6) {
      params["properties"]['file_id'] = content;
    } else if (value == 7) {
      params["properties"]['brightness_value'] = content;
    } else if (value == 11) {
      params["properties"]['volume_value'] = content;
    } else if (value == 16) {
      params["properties"]['adjustment_value'] = content;
    } else if (value == 33) {
      params["properties"]['play_mode'] = content;
    } else if (value == 35) {
      params["properties"]['speed_value'] = content;
    }
    print("params ------> ${convert.jsonEncode(params)}");
    if (_channel != null) {
      _channel!.sink.add(convert.jsonEncode(params));
    }
  }

  onDone() {
    print("消息关闭");
    if (_channel != null) {
      _channel!.sink.close();
    }
    _channel = null;
  }

  onError(err) {
    print("消息错误${err}");
    if (_channel != null) {
      _channel!.sink.close();
    }
    _channel = null;
  }

  onData(event) {
    try {
      if (event != null) {
        print('event ------->${event}');
        if (event.runtimeType != String) {
          return;
        }

        Map<String, dynamic> map = convert.jsonDecode(event);
        deviceID = map['properties']['id'];
        _cmdData.deviceID = deviceID;
        // print('map ------->${map}');
        int type = map['cmd'];
        switch (type) {
          case 26:
            /*{
              'cmd': 26,
              'destination': 0,
              'order': 65,
              'pack_count': 1,
              'pack_order': 1,
              'properties': {
                'bluetooth_state': 2,
                'brightness': 15,
                'file_id': 0,
                'id': '6C21A2232FEF',
                'info_show': 0,
                'ip': '192.168.43.1',
                'memory': 3779,
                'model': 0,
                'open': true,
                'packet_type': 0,
                'pause': false,
                'play_mode': 1,
                'type': 0,
                'volume': 15,
                'wifi_signal': 0
              },
              'source': 15067,
              'version_code': 700077
            };*/
            // if (!_cmdData.isSliderScr) {
            // _cmdData.getDeviceInfo(map);
            // _drawerData.initState(map);
            // }
            if (!_cmdData.isOnce) {
              _cmdData.isOnce = true;
              _cmdData.getDeviceInfo(map);
              _drawerData.initState(map);
            }
            break;
          case 30:
            /*Map a = {
              'cmd': 30,
              'destination': 0,
              'order': 63,
              'pack_count': 1,
              'pack_order': 1,
              'properties': {
                'down_thum': 'http',
                'file': [
                  {
                    'file_id': 1,
                    'file_name': 1,
                    'file_type': 2,
                    'pack_number': 1,
                    'percentage': 100,
                    'play_count': 1,
                    'play_order': 1,
                    'thum_path': '/storage/emulated/0/pointPicFile/1.png'
                  },
                  {
                    'file_id': 2,
                    'file_name': 2,
                    'file_type': 2,
                    'pack_number': 2,
                    'percentage': 100,
                    'play_count': 1,
                    'play_order': 2,
                    'thum_path': '/storage/emulated/0/pointPicFile/2.png'
                  },
                  {
                    'file_id': 3,
                    'file_name': 3,
                    'file_type': 2,
                    'pack_number': 3,
                    'percentage': 100,
                    'play_count': 1,
                    'play_order': 3,
                    'thum_path': '/storage/emulated/0/pointPicFile/3.png'
                  }
                ],
                'id': '6C21A2232FEF'
              },
              'source': 15067,
              'version_code': 700077
            };*/
            _cmdData.medisType = map['properties']['down_thum'];
            _cmdData.getMedisList(map['properties']['file']);
            break;
          case 64:
            _cmdData.deviceInfo = map;
            break;
        }
      }
    } catch (e) {
      print(e);
    }
  }

  void dispose() {
    if (_channel != null) {
      _channel!.sink.close();
    }
    _channel = null;
    if (_timer != null) {
      _timer!.cancel();
    }
    _timer = null;
  }
}
